using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

using Jeffrey.XFramework.XCrawl;

namespace Jeffrey.XFramework.XNet
{
    public static class DnsCache
    {
        private static readonly Object s_SyncRoot = new Object();

        private static readonly String s_HostNotFound = "HNF";

        static DnsCache()
        {
            m_DnsLookup = new Dictionary<UInt32, String>();
        }

        public static IPAddress[] DnsLookUp(CrawlUri curi)
        {
            return DnsLookUp(curi.Host);
        }

        public static IPAddress[] DnsLookUp(String Hostname)
        {
            UInt32 Hash  = CrawlToolKits.StringHash(Hostname);

            lock (s_SyncRoot)
            {
                if (m_DnsLookup.ContainsKey(Hash))
                {
                    String sip = m_DnsLookup[Hash];

                    if (sip != s_HostNotFound)
                        return new IPAddress[] { IPAddress.Parse(sip) };
                    else
                        return null;
                }
            }
            try
            {
                return Dns.GetHostAddresses(Hostname);
            }
            catch (SocketException se)
            {
                if (se.SocketErrorCode == SocketError.HostNotFound)
                    m_DnsLookup[Hash] = s_HostNotFound;

                return null;
            }
        }

        public static void CacheIP(String Hostname, IPAddress IP)
        {
            lock(s_SyncRoot)
                m_DnsLookup[CrawlToolKits.StringHash(Hostname)] = IP.ToString();
        }

        public static void CacheFailed(String Hostname)
        {
            UInt32 Hash = CrawlToolKits.StringHash(Hostname);

            lock (s_SyncRoot)
            {
                if (m_DnsLookup.ContainsKey(Hash))
                    m_DnsLookup.Remove(Hash);
            }
        }

        public static void Release()
        {
            m_DnsLookup.Clear();
        }

        private static Dictionary<UInt32, String> m_DnsLookup;
    }
}
